package com.cmc.cloud.cmclink.doc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cmc.cloud.cmclink.bdt.api.base.dto.resp.VesselNameDataRespDTO;
import com.cmc.cloud.cmclink.doc.constants.CommonConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.ApiErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.convert.ApprovePermissionConfigConvert;
import com.cmc.cloud.cmclink.doc.entity.ApprovePermissionConfigDO;
import com.cmc.cloud.cmclink.doc.mapper.ApprovePermissionConfigMapper;
import com.cmc.cloud.cmclink.doc.rpcservice.NucTransferService;
import com.cmc.cloud.cmclink.doc.rpcservice.VesselTransferService;
import com.cmc.cloud.cmclink.doc.service.ApprovePermissionConfigService;
import com.cmc.cloud.cmclink.doc.vo.special.approvepermissionvo.ApprovePermissionConfigUpdateReqVO;
import com.cmc.cloud.cmclink.doc.vo.special.approvepermissionvo.ApprovePermissionConfigUserRespVO;
import com.cmc.cloud.cmclink.doc.vo.special.approvepermissionvo.ApprovePermissionReqVO;
import com.cmc.cloud.cmclink.doc.vo.special.approvepermissionvo.UserWithApprovePermissionRespVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户船舶审批权限配置 Service 实现类
 *
 * @author 集运管理员
 */
@Service
@Validated
@Slf4j
public class ApprovePermissionConfigServiceImpl implements ApprovePermissionConfigService {

    @Resource
    private ApprovePermissionConfigMapper approvePermissionConfigMapper;

    @Resource
    private VesselTransferService vesselService;

    @Resource
    private NucTransferService nucService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateApprovePermissionConfig(ApprovePermissionConfigUpdateReqVO updateReqVO) {
        // 插入新数据
        Long userId = getUserIdByName(updateReqVO.getUserCode());
        List<ApprovePermissionConfigDO> approvePermissionConfigDOList =
                ApprovePermissionConfigConvert.INSTANCE.convertDOList(updateReqVO.getVesselNameBaseVos(), userId);
        approvePermissionConfigDOList.forEach(approveDO -> approveDO.setUserId(userId));
        approvePermissionConfigMapper.insertBatch(approvePermissionConfigDOList);
    }

    @Override
    public List<VesselNameDataRespDTO> getApprovePermissionConfigWithoutUser(ApprovePermissionReqVO reqVo) {
        List<VesselNameDataRespDTO> vesselNameDataRespDTOList = vesselService.getVesselNamesData(reqVo.getVesselCode());
        List<ApprovePermissionConfigDO> approvePrmeissionConfigDOList = getApprovePermissionConfigDO(reqVo.getUserCode());
        Set<String> vesselCode = new HashSet<>();
        approvePrmeissionConfigDOList.forEach(userDO -> vesselCode.add(userDO.getVesselCode()));
        return vesselNameDataRespDTOList.stream().filter(allVesselDTO -> {
            if (reqVo.getShowNotUse()) {
                return !vesselCode.contains(allVesselDTO.getVesselCode());
            } else {
                if (allVesselDTO.getEnabled() == null) {
                    return false;
                }
                return allVesselDTO.getEnabled() && !vesselCode.contains(allVesselDTO.getVesselCode());
            }
        }).collect(Collectors.toList());
    }

    @Override
    public UserWithApprovePermissionRespVO getApprovePermissionConfigWithUser(ApprovePermissionReqVO reqVo) {
        List<VesselNameDataRespDTO> vesselNameDataRespDTOList = vesselService.getVesselNamesData(reqVo.getVesselCode());
        List<ApprovePermissionConfigDO> approvePermissionConfigDOList = getApprovePermissionConfigDO(reqVo.getUserCode());
        Map<String, VesselNameDataRespDTO> allMap =
                new HashMap<>(Math.max(CommonConstants.DEFAULT_MAP_COUNT, vesselNameDataRespDTOList.size()));
        vesselNameDataRespDTOList.forEach(allDTO -> allMap.put(allDTO.getVesselCode(), allDTO));
        List<ApprovePermissionConfigUserRespVO> respVOList = new ArrayList<>();
        UserWithApprovePermissionRespVO respVO = new UserWithApprovePermissionRespVO();
        respVO.setNonOwnedShip(Boolean.FALSE);
        for (ApprovePermissionConfigDO userDo : approvePermissionConfigDOList) {
            VesselNameDataRespDTO tempDTO = allMap.getOrDefault(userDo.getVesselCode(), null);
            if (tempDTO == null) {
                continue;
            }
            if("NonOwnedShip".equals(userDo.getVesselCode())){
                respVO.setNonOwnedShip(Boolean.TRUE);
                continue;
            }
            ApprovePermissionConfigUserRespVO permission = ApprovePermissionConfigConvert.INSTANCE.convert(userDo);
            permission.setVesselNameCn(tempDTO.getVesselNameCn());
            permission.setVesselNameEn(tempDTO.getVesselNameEn());
            permission.setEnabled(tempDTO.getEnabled());
            permission.setUserCode(reqVo.getUserCode());
            respVOList.add(permission);
            respVO.setUserPermissions(respVOList);
        }
        return respVO;
    }

    @Override
    public void deleteApprovePermissionConfig(ApprovePermissionConfigUpdateReqVO updateReqVo) {
        Long userId = getUserIdByName(updateReqVo.getUserCode());
        LambdaQueryWrapper<ApprovePermissionConfigDO> queryWrapper = Wrappers.<ApprovePermissionConfigDO>lambdaQuery()
                .eq(ApprovePermissionConfigDO::getUserId, userId).in(ApprovePermissionConfigDO::getVesselCode, updateReqVo.getVesselCodes());
        approvePermissionConfigMapper.delete(queryWrapper);
    }

    @Override
    public void setNonOwnedShip(ApprovePermissionReqVO reqVo) {
        Long userId = getUserIdByName(reqVo.getUserCode());
        ApprovePermissionConfigDO approvePermissionConfigDo = approvePermissionConfigMapper.selectOne(new LambdaQueryWrapperX<ApprovePermissionConfigDO>()
                .eq(ApprovePermissionConfigDO::getUserId, userId)
                .eq(ApprovePermissionConfigDO::getVesselCode, "NonOwnedShip").last("limit 1"));
        if (reqVo.getNonOwnedShip()) {
            if (null == approvePermissionConfigDo) {
                approvePermissionConfigDo = new ApprovePermissionConfigDO();
                approvePermissionConfigDo.setUserId(userId);
                approvePermissionConfigDo.setVesselCode("NonOwnedShip");
                approvePermissionConfigMapper.insert(approvePermissionConfigDo);
            }
        } else {
            if (null != approvePermissionConfigDo) {
                approvePermissionConfigMapper.deleteById(approvePermissionConfigDo.getId());
            }
        }
    }

    private Long getUserIdByName(String userCode) {
        Long userId = nucService.getUserProfileByName(userCode).getId();
        if (userId == null) {
            throw ServiceExceptionUtil.exception(ApiErrorCodeConstants.NUC_GET_USER_PROFILE_BY_NAME_NULL);
        }
        return userId;
    }

    private List<ApprovePermissionConfigDO> getApprovePermissionConfigDO(String userCode) {
        Long userId = getUserIdByName(userCode);
        LambdaQueryWrapper<ApprovePermissionConfigDO> queryWrapper =
                Wrappers.<ApprovePermissionConfigDO>lambdaQuery().eq(ApprovePermissionConfigDO::getUserId, userId);
        return approvePermissionConfigMapper.selectList(queryWrapper);
    }
}
